package com.example.netty.io.server

import androidx.annotation.IntRange
import com.example.netty.io.core.IMessageListener
import com.example.netty.io.core.NettyLog
import com.example.netty.io.core.NioSocketTask
import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.Channel
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelFutureListener
import io.netty.channel.ChannelOption
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioServerSocketChannel
import java.io.IOException

private const val TAG = "NettyServer"

class NettyServerTask(
    @IntRange(from = 1000, to = 65535)
    private val port: Int,
    private val iMessageListener: IMessageListener
) : NioSocketTask() {
    override fun release() {

    }

    override fun run() {
        val eventLoopGroup = NioEventLoopGroup(1)
        val workGroup = NioEventLoopGroup()
        val handler = ServerChannelHandler(iMessageListener)
        try {
            val serverBootstrap = ServerBootstrap()
            serverBootstrap.group(eventLoopGroup, workGroup)
                .channel(NioServerSocketChannel::class.java)
                .childHandler(handler)
                .option(ChannelOption.SO_KEEPALIVE,true)
                .option(ChannelOption.TCP_NODELAY,true)
                .option(ChannelOption.SO_BACKLOG, 128)

            val channelFuture = serverBootstrap.bind(port).sync()

            channelFuture.addListener(object : ChannelFutureListener {
                override fun operationComplete(future: ChannelFuture) {
                    if (future.isSuccess) {
                        onSuccess(future.channel())
                        NettyLog.d(TAG, "future connect success $port")
                    } else {
                        NettyLog.d(TAG, "future connect failed")
                    }
                }
            })
            channel = channelFuture.channel()
            channelFuture.channel().closeFuture().sync()
            NettyLog.d(TAG, "closeFuture 关闭成功")
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                eventLoopGroup.shutdownGracefully().sync()
                workGroup.shutdownGracefully().sync()
                close()
                NettyLog.d(TAG, "finally")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}